<!-- eslint-disable no-eval -->
<template>
  <a-select
    optionFilterProp="label"
    allowClear
    :tokenSeparators="[' ', ',']"
    placeholder="请选择"
    v-model:value="selectValue"
    v-bind="attrs"
    :filterOption="filterOption || localFilterOption"
    v-on:[searchEventName]="toSearch"
    :dropdownStyle="{ zIndex: 9999 }"
  >
    <template v-if="fetching" #notFoundContent>
      <a-spin size="small" />
    </template>
    <slot :options="optionDatas">
      <a-select-option
        :key="item[labelValue] || index"
        :value="item[labelValue]"
        :item="item"
        :label="item[label]"
        :disabled="disabledKeys.includes(item[labelValue])"
        v-for="(item, index) in optionDatas"
        >{{ item[label] }}</a-select-option
      >
    </slot>
  </a-select>
</template>
<script setup>
import { ref, onMounted, watch, computed, toRaw, useAttrs } from 'vue'
import { post, get } from 'server/axios'
import { debounce } from 'lodash-es'
import { evalPropChain, isNumber } from '@/utils/utils.js'

const emit = defineEmits(['update:value', 'update:options'])

// const slots = useSlots()

const attrs = useAttrs()

const props = defineProps({
  value: [String, Number, Array],
  url: String,
  // 下拉框显示的文本字段
  label: {
    type: String,
    default: 'label'
  },
  // 下拉框值的字段
  labelValue: {
    type: String,
    default: 'value'
  },
  // 模糊搜索的关键词字段
  searchField: {
    type: String,
    default: ''
  },
  // 请求接口参数
  params: {
    type: Object,
    default: () => {
      return {}
    }
  },
  disabledKeys: {
    type: Array,
    default: () => []
  },
  // 支持自定义传options
  options: {
    type: Array,
    default: () => []
  },
  method: {
    type: String,
    default: 'post'
  },
  respField: {
    type: String,
    default: 'data'
  },
  immediate: {
    type: Boolean,
    default: false
  },
  filterOption: {
    type: Function,
    default: null
  }
})
const AXIOS_METHOD = {
  get: get,
  post: post
}
const optionDatas = ref(props.options || [])
// 定义loading
const fetching = ref(false)

// 请求接口参数
let reqParams = toRaw(props.params || {})

/**
 * 计算双向绑定的值
 */
const selectValue = computed({
  get() {
    return props.value || undefined
  },
  set(value) {
    emit('update:value', value)
  }
})
// 计算是否存在远程搜索事件
const searchEventName = computed(() => {
  return props.searchField ? 'search' : ''
})
const getServeUrl = () => {
  return props.url.startsWith('http')
    ? props.url
    : `${process.env.VUE_APP_CONFIG}/${props.url}`
}

// 处理rollup打包eval不允许使用问题

// 拉取options数据
const queryServiceData = async () => {
  const resp = await AXIOS_METHOD[props.method.toLowerCase()](
    getServeUrl(),
    reqParams
  )
  if (!resp.success) {
    emit('update:options', [])
    return false
  }

  const data = evalPropChain(resp, props.respField)
  if (Object.prototype.toString.call(data) === '[object Object]') {
    optionDatas.value = Object.keys(data).map(key => {
      return {
        label: data[key],
        value: isNumber(key) ? parseInt(key) : key
      }
    })
  } else {
    if (typeof data[0] !== 'object') {
      optionDatas.value = data.map(item => {
        return {
          label: item,
          value: item
        }
      })
    } else {
      optionDatas.value = data
    }
  }
  emit('update:options', optionDatas.value)
}

/**
 * 关键词远程搜索
 */
const toSearch = debounce(keyWord => {
  reqParams[props.searchField] = keyWord
  queryServiceData()
}, 300)

watch(
  () => props.params,
  (newV, v) => {
    if (JSON.stringify(newV) !== JSON.stringify(v)) {
      if (props.url) {
        reqParams = props.params || {}
        queryServiceData()
      }
    }
  }
)
const localFilterOption = (input, option) => {
  if (!option.children) return
  return (
    option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
  )
}

onMounted(() => {
  if (props.url && props.immediate) {
    queryServiceData()
  }
})
</script>
<style lang="scss" scoped></style>
